package com.example.security.controller;

import com.example.security.common.Result;
import com.example.security.config.JwtProperties;
import com.example.security.entity.SysUser;
import com.example.security.exception.InvalidTokenException;
import com.example.security.service.UserService;
import com.example.security.vo.SsoTokenResponse;
import com.example.security.vo.SsoUserInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.annotation.*;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.Claims;
import java.util.Date;
import java.util.Set;
import java.util.HashSet;

@Slf4j
@RestController
@RequestMapping("/api/oauth")
@RequiredArgsConstructor
public class SsoEndpointController {

    private final UserService userService;
    private final PasswordEncoder passwordEncoder;
    private final JwtProperties jwtProperties;

    @PostMapping("/token")
    public SsoTokenResponse token(
            @RequestParam("userId") Long userId,
            @RequestParam("password") String password,
            @RequestParam("grant_type") String grantType) {
        
        try {
            // 直接通过userId查找用户
            SysUser user = userService.getByUserId(userId);
            if (user == null || !passwordEncoder.matches(password, user.getPassword())) {
                log.warn("Authentication failed for userId: {}, reason: {}", 
                    userId, (user == null ? "User not found" : "Invalid password"));
                throw new BadCredentialsException("Invalid userId or password");
            }

            // 获取用户权限
            Set<String> permissions = userService.getUserPermissions(user.getId());

            // 生成JWT token
            String token = Jwts.builder()
                .setSubject(user.getId().toString())
                .claim("username", user.getUsername())
                .claim("permissions", permissions)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + jwtProperties.getExpireTime() * 1000))
                .signWith(SignatureAlgorithm.HS256, jwtProperties.getSecretBytes())
                .compact();

            // 生成token响应
            SsoTokenResponse response = new SsoTokenResponse();
            response.setAccessToken(token);
            response.setTokenType("Bearer");
            response.setExpiresIn(jwtProperties.getExpireTime());
            
            log.debug("Generated token for userId: {}", userId);
            return response;
        } catch (BadCredentialsException e) {
            throw e;
        } catch (Exception e) {
            log.error("Token generation failed", e);
            throw new BadCredentialsException("Authentication failed: " + e.getMessage());
        }
    }

    @PostMapping("/user-info")
    public SsoUserInfo userInfo(@RequestHeader("Authorization") String authorization) {
        try {
            // 从Authorization中提取token
            String token = authorization.substring(7); // 去掉"Bearer "前缀
            
            // 解析JWT token
            Claims claims = Jwts.parser()
                .setSigningKey(jwtProperties.getSecretBytes())
                .parseClaimsJws(token)
                .getBody();
            
            Long userId = Long.parseLong(claims.getSubject());
            
            // 获取用户信息
            SysUser user = userService.getByUserId(userId);
            if (user == null) {
                throw new InvalidTokenException("Invalid token");
            }

            // 转换为SsoUserInfo
            SsoUserInfo userInfo = new SsoUserInfo();
            userInfo.setUserId(user.getId());
            userInfo.setUsername(user.getUsername());
            userInfo.setName(user.getName());
            userInfo.setEmail(user.getEmail());
            userInfo.setPhone(user.getPhone());
            
            // 获取并设置权限
            Set<String> permissions = userService.getUserPermissions(user.getId());
            userInfo.setPermissions(permissions != null ? permissions : new HashSet<>());
            
            return userInfo;
        } catch (InvalidTokenException e) {
            throw e;
        } catch (Exception e) {
            log.error("Failed to get user info", e);
            throw new BadCredentialsException("Failed to get user info: " + e.getMessage());
        }
    }
} 